import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
//
//public class Test {
//    public static void main(String[] args) throws InterruptedException{
//        BlockingQueue<String> queue = new ArrayBlockingQueue<>(100);
//        queue.put("hello");
//        System.out.println(queue.take());
//        System.out.println(queue.take());
//    }
//}


//模拟实现阻塞队列
class MyBlockingQueue {
    private String[] elems = null;
    private int head = 0;
    private int tail = 0;
    private int size = 0;
    Object locker = new Object();

    public MyBlockingQueue(int capacity) {
        elems = new String[capacity];
    }

    public void put(String elem) throws InterruptedException{
        synchronized (locker) {
            while (size >= elems.length) {
                locker.wait();
            }

            elems[tail] = elem;
            tail++;
            if(tail >= elems.length) {
                tail = 0;
            }

            size++;
            //入队列成功后唤醒
            locker.notify();
        }
    }

    public String take() throws InterruptedException{
        String elem = null;
        synchronized (locker) {
            while (size == 0) {
                locker.wait();
            }

            elem = elems[head];
            head++;
            if(head >= elems.length) {
                head = 0;
            }
            size--;

            //元素出队列成功后唤醒
            locker.notify();
        }

        return elem;
    }
}


// 单例模式

class SingletonLazy {
    public volatile SingletonLazy instance = null;
    Object locker = new Object();
    public SingletonLazy getInstance () {
        if(instance == null) {
            synchronized (locker) {
                if(instance == null) {
                    instance = new SingletonLazy();
                }
            }
        }
        return instance;
    }

    private SingletonLazy(){};
}


public class Test {
    public static void main(String[] args) {
        MyBlockingQueue queue = new MyBlockingQueue(100);
        Thread t1 = new Thread(()-> {
            int i = 0;
            while(true) {
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                try {
                    queue.put(i + "");
                    System.out.println("生产" +i);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                i++;
            }
        });

        Thread t2 = new Thread(()-> {
            while(true) {
                try {
                    String elem = queue.take();
                    System.out.println("消费" + elem);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });

        t1.start();
        t2.start();
    }
}
